package com.regan.erp.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.jfinal.kit.Kv;
import com.regan.erp.model.Menu;
import com.regan.erp.model.User;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 授权工具类
 *
 * @author zhangby
 * @date 2018/10/23 下午4:28
 */
public class AuthUtil {
    /** 角色菜单数据 */
    private static final String USER_ROLE_MENU_DATA = "user_role_menu_data";
    /** 角色菜单分组 */
    private static final String USER_ROLE_MENU_TYPE = "user_role_menu_type";
    /** 角色授权 */
    private static final String USER_ROLE_PERMISSION = "user_role_permission";

    /**
     * 获取用户所有菜单
     * @param user_id 用户id
     * @return
     */
    public static List<Menu> getUserAllMenu(String user_id){
        //从redis里获取授权菜单
        String redisKey = StrUtil.format(ConfigUtil.redisKey().get(USER_ROLE_MENU_DATA), user_id);
        List<Menu> menuList = RedisUtil.getArray(redisKey, Menu.class);
        //判断是否为空
        if (ObjectUtil.isNull(menuList)) {
            /** 查询授权菜单 */
            //获取用户信息
            User user = UserUtil.getUserById(user_id);
            //查询用户角色
            List<Integer> roles = user.getRole();
            //获取角色菜单
            List<Menu> allMenuList = Lists.newArrayList();
            roles.forEach(rId ->{
                //加入菜单
                List<Menu> menus = Menu.dao.find("select tm.* from t_menu tm \n" +
                        "join t_role_menu  trm on tm.id=trm.menu_id \n" +
                        "join t_role tr on tr.id = trm.role_id \n" +
                        "where role_id=? \n" +
                        "and tm.del_flag=0 and tm.is_show=1\n" +
                        "and tr.del_flag=0 and tr.status=0 order by tm.sort", rId);
                allMenuList.addAll(menus);
            });
            //过滤重复菜单
            menuList = allMenuList.stream().distinct().collect(Collectors.toList());
            RedisUtil.set(redisKey,menuList);
        }
        return menuList;
    }

    /**
     * 获取角色授权菜单
     * @return
     */
    public static List<Kv> getUserRoleMenu(String user_id,String type) {
        //从redis里获取授权菜单
        String redisKey = StrUtil.format(ConfigUtil.redisKey().get(USER_ROLE_MENU_TYPE), user_id,type);
        List<Kv> menuList = RedisUtil.getArray(redisKey, Kv.class);
        //判断是否为空
        if (ObjectUtil.isNull(menuList)) {
            menuList = FunctionUtils.convers(
                    getUserAllMenu(user_id).stream()
                            .filter(menu -> ObjectUtil.equal(menu.getType(), type)).collect(Collectors.toList()),
                    menu -> {
                        //获取首个子菜单
                        String href = "/";
                        try {
                            if ("1".equals(type)) {
                                href = getUserAllMenu(user_id).stream()
                                        .filter(m -> ObjectUtil.equal(m.getParentId(), menu.getId()))
                                        .sorted(Comparator.comparing(Menu::getSort))
                                        .findFirst().get().getHref();
                            } else {
                                href = menu.getHref();
                            }
                        } catch (Exception e) {
                            //无需处理
                        }
                        return Kv.create()
                                .set("name", menu.getName())
                                .set("path", href)
                                .set("icon", menu.getIcon());
                    });
            RedisUtil.set(redisKey,menuList);
        }
        return menuList;
    }

    /**
     * 获取用户角色授权标识
     * @param user_id 用户id
     * @return
     */
    public static List<String> getUserRolePermission(String user_id) {
        //从redis里获取授权菜单
        String redisKey = StrUtil.format(ConfigUtil.redisKey().get(USER_ROLE_PERMISSION), user_id);
        List<String> permissions = RedisUtil.getArray(redisKey, String.class);
        //判断是否为空
        if (ObjectUtil.isNull(permissions)) {
            /** 查询授权标识 */
            //获取用户信息
            User user = UserUtil.getUserById(user_id);
            //初始化
            List<String> rsList = Lists.newArrayList();
            user.getRole().forEach(rid->{
                //加入菜单
                List<Menu> menus = Menu.dao.find("select tm.* from t_menu tm \n" +
                        "join t_role_menu  trm on tm.id=trm.menu_id \n" +
                        "join t_role tr on tr.id = trm.role_id \n" +
                        "where role_id=? and tm.permission is not null \n" +
                        "and tm.del_flag=0 and tm.is_show=1\n" +
                        "and tr.del_flag=0 and tr.status=0 order by tm.sort", rid);
                rsList.addAll(FunctionUtils.convers(menus, Menu::getPermission));
            });
            permissions = rsList.stream().distinct().collect(Collectors.toList());
            //加入redis
            RedisUtil.set(redisKey,permissions);
        }
        return permissions;
    }

    /**
     * 刷新角色授权菜单缓存
     */
    public static void clearUserRoleAuth(String user_id) {
        //从redis里获取授权菜单数据
        String redisKey1 = StrUtil.format(ConfigUtil.redisKey().get(USER_ROLE_MENU_DATA), user_id);
        //从redis里获取授权菜单
        String redisKey2 = StrUtil.format(ConfigUtil.redisKey().get(USER_ROLE_PERMISSION), user_id);
        RedisUtil.del(redisKey1);
        RedisUtil.del(redisKey2);
        //从redis里获取授权菜单分组
        RedisUtil.del(StrUtil.format(ConfigUtil.redisKey().get(USER_ROLE_MENU_TYPE), user_id,"1"));
        RedisUtil.del(StrUtil.format(ConfigUtil.redisKey().get(USER_ROLE_MENU_TYPE), user_id,"2"));
        RedisUtil.del(StrUtil.format(ConfigUtil.redisKey().get(USER_ROLE_MENU_TYPE), user_id,"3"));
    }

    /**
     * 验证用户操作权限
     * @param user_id 用户id
     * @param permissions 权限标识
     * @return
     */
    public static Boolean verifyAuth(String user_id,String permissions) {
        //获取用户权限标识
        List<String> userRolePermission = getUserRolePermission(user_id);
        return userRolePermission.contains(permissions);
    }
}
